using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading;
using log4net.Core;

namespace Comteck.Winforms.Tasks {
  /// <summary>
  /// 返回结果
  /// </summary>
  /// <typeparam name="T"></typeparam>
  public class WorkerManager<T> : BaseLog, IDisposable {

    private ManualResetEvent workExit = new ManualResetEvent(true);
    private ManualResetEvent mreExit = new ManualResetEvent(false);

    int WAIT_COUNT = 250;


    #region 构造函数

    public WorkerManager(Action<T> action) {
      Work_Action = action;
    }

    public WorkerManager(Action<T> action, int wait_count) : this(action) {
      WAIT_COUNT = wait_count;
    }


    #endregion


    Thread thread = null;

    /// <summary>
    /// 是否运行
    /// </summary>
    private volatile bool IsRun = false;

    /// <summary>
    /// 开始工作
    /// </summary>
    public void Start(T t) {
      thread?.Close();
      IsRun = true;
      mreExit.Reset();
      thread = new Thread(work);
      thread.IsBackground = true;
      thread.Start(t);
      Logger.Info($"开始工作:{thread?.Name}{ thread?.ThreadState}");
    }

    /// <summary>
    /// 停止工作
    /// </summary>
    public void Stop() {
      Logger.Info($"停止工作:{thread?.Name}{ thread?.ThreadState}");
      IsRun = false;
      mreExit.Set();
      thread?.Close();
    }

    //工作内容
    private Action<T> Work_Action;

    /// <summary>
    /// 工作线程
    /// </summary>
    /// <param name="t"></param>
    [HandleProcessCorruptedStateExceptions]
    private void work(object t) {
      Logger.Info($"工作线程[work]..开始");

      workExit.Reset();

      //循环
      while (IsRun) {
        //等待
        if (mreExit.WaitOne(WAIT_COUNT)) {
          break;
        }

        try {
          //工作
          Work_Action?.Invoke((T)t);
        } catch (Exception ex) {
          Logger.Info($"工作线程[work]异常:{ex.StackTrace}");
          continue;
        }
      }

      workExit.Set();

      Logger.Info($"工作线程[work]..退出");
    }

    public void Dispose() {
      Logger.Info($"工作线程释放:{thread?.Name}{ thread?.ThreadState}");
    }
  }
}
